package com.panda.utils;

import com.panda.pojo.Context;
import com.panda.pojo.Element;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtils {


    private static Set<Pattern> sps;

    static {

        sps = new LinkedHashSet<>();

        sps.add(Pattern.compile("\'[^\']*\'"));
        sps.add(Pattern.compile("\"[^\"]*\""));

        //保护其中的正则表达式
        //sps.add(Pattern.compile("/[^*][^/]+[^*]/"));

    }

    private static Pattern expression = Pattern.compile("#\\{([^#]+)}#");

    //需要被保护的正则
    public static void addProtectPattern(Pattern pattern) {
        sps.add(pattern);
    }

    static void extract(Context context) {
        context.setText(extract(context, context.getText()));
    }

    static String extract(Map<String, String> map, String s) {


        for (Pattern pattern : sps) {


            Matcher matcher = pattern.matcher(s);

            while (matcher.find()) {

                String group = matcher.group();

                String id = IdUtils.create("__string_");

                s = s.replace(group, " " + id + " ");

                map.put(id, group);

            }
        }

        return expression(map, s);
    }

    private static String expression(Map<String, String> map, String s) {

        Matcher matcher = expression.matcher(s);

        while (matcher.find()) {

            String t = "'{{" + matcher.group(1) + "}}'";

            String id = IdUtils.create("__string_");

            s = s.replace(matcher.group(), " " + id + " ");

            map.put(id, t);

        }

        return s;
    }

    private static String extract(Context context, String s) {

        Map<String, String> map = context.getStringMap();
        return extract(map, s);
    }

    static void removeAnnotation(Context context) {
        context.setText(StringUtils.removeAnnotation(context.getText()));
    }

    static String removeAnnotation(String s) {

        s = removeAnnotationMultiLine(s);

        s = removeAnnotationSingleLine(s);

        return s;
    }


    private static String removeAnnotationMultiLine(String s) {

        Pattern pattern = Pattern.compile("/\\*[^*]*\\*/");


        Matcher matcher = pattern.matcher(s);

        if (matcher.find()) {
            s = s.replace(matcher.group(), "");

        } else {
            return s;
        }

        while (matcher.find()) {
            s = s.replace(matcher.group(), "");
        }


        //递归
        return removeAnnotationMultiLine(s);

    }


    private static final Pattern slp = Pattern.compile("//[^\n]*\n");

    private static String removeAnnotationSingleLine(String s) {


        Matcher matcher = slp.matcher(s);

        while (matcher.find()) {
            s = s.replace(matcher.group(), "");
        }

        return s;

    }


    private static final Pattern sp = Pattern.compile("__string_[a-zA-Z][a-zA-Z0-9]*_[0-9]+");

    static List<String> transform2output(String s) {

        List<String> strings = new ArrayList<>();

        Matcher matcher = sp.matcher(s);

        int end = 0;

        String substring;

        while (matcher.find()) {

            substring = s.substring(end, matcher.start()).trim();

            if (!"".equals(substring)) {
                strings.add(substring);
            }

            strings.add(matcher.group());

            strings.add("<<");

            end = matcher.end();

        }


        substring = s.substring(end).trim();

        if (!"".equals(substring)) {
            strings.add(substring);
        }


        return strings;
    }


    static String fillProtected(Element element, String s) {

        Set<String> protectedStrings = element.getProtectedStrings();

        Map<String, String> stringMap = element.getContext().getStringMap();

        for (String string : protectedStrings) {

            s = s.replace(string, stringMap.get(string));

        }

        return s;

    }

    public static String fillBack(Map<String, String> map, String text) {

        Stack<String> stack = new Stack<>();

        map.keySet().forEach(stack::push);

        while (!stack.empty()) {
            String id = stack.pop();
            text = text.replace(id, map.get(id));
        }

        //最后再将字符串替换回
        return text.replace("__string__'", "").replace("__string__\"", "").replace("'__string__", "").replace("\"__string__", "");

    }

}
